package com.chenl.provider.DEMOS.Quartz.dynamicQuartz.util;

import com.chenl.provider.DEMOS.Quartz.dynamicQuartz.vo.JobVo;
import com.chenl.provider.DEMOS.Quartz.dynamicQuartz.po.SysJob;
import com.chenl.provider.DEMOS.Quartz.dynamicQuartz.zenum.ActionEnum;
import com.chenl.provider.DEMOS.Quartz.dynamicQuartz.zenum.JobEnum;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.util.ObjectUtils;
 
import java.lang.reflect.Method;
import java.util.Date;

@Slf4j
public class QuartzUtil {
 
    @SneakyThrows
    public static void startJob(SysJob sysJob) {
        // 获取调度器 Scheduler
        Scheduler scheduler = SchedulerStatic.getScheduler();
        Long jobId = sysJob.getId();
        String jobGroup = sysJob.getJobGroup();
 
        // 构造一个job
        JobKey jobKey = JobKey.jobKey(jobId.toString(), jobGroup);
        JobDetail jobDetail = JobBuilder
                .newJob(QuartzJob.class)
                .withIdentity(jobKey)
                .build();
 
        // 构造cron调度器
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(sysJob.getCronExpression());
        getMisfirePolicy(sysJob, cronScheduleBuilder);
 
        // 构造触发器 trigger
        TriggerKey triggerKey = TriggerKey.triggerKey(jobId.toString(), jobGroup);
        CronTrigger trigger = TriggerBuilder
                .newTrigger()
                .withIdentity(triggerKey)
                .withSchedule(cronScheduleBuilder)
                .build();
 
        // 放入job信息,为后续执行改任务的具体方法做铺垫(需要反射调用), 在execute中获取并应用
        jobDetail.getJobDataMap().put(JobEnum.Key.getCode(), sysJob);
        // 判断该任务是否存在,修改任务,先删除然后添加
        if (scheduler.checkExists(jobKey)) {
            // 防止创建时存在数据问题 先移除，然后在执行创建操作
            scheduler.deleteJob(jobKey);
        }
        // 判断任务是否过期
        CronExpression cron = new CronExpression(sysJob.getCronExpression());
        Date nextValidTimeAfter = cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
        if (!ObjectUtils.isEmpty(nextValidTimeAfter)) {
            // 执行调度任务
            scheduler.scheduleJob(jobDetail, trigger);
        }
    }
 
 
    @SneakyThrows
    public static Object doJob(JobVo sysJob, String action) {
        // 获取调度器 Scheduler
        Scheduler scheduler = SchedulerStatic.getScheduler();
        // 构造一个job
        JobKey jobKey = JobKey.jobKey(sysJob.getJobId().toString(), sysJob.getJobGroup());
        // 判断该任务是否存在,修改任务,先删除然后添加
        if (!scheduler.checkExists(jobKey)) {
            return Boolean.FALSE;
        }
        switch (action){
            case ActionEnum.check:    //
                return Boolean.TRUE;
            case ActionEnum.pause:   //暂停
                scheduler.pauseJob(jobKey);
                break;
            case ActionEnum.resume:   //继续
                scheduler.resumeJob(jobKey);
                break;
            case ActionEnum.delete:    //删除
                scheduler.deleteJob(jobKey);
                break;
            default:
                scheduler.checkExists(jobKey);
                break;
        }
        return null;
    }

    public static String getStatus(JobVo sysJob) throws SchedulerException {
        // 获取调度器 Scheduler
        Scheduler scheduler = SchedulerStatic.getScheduler();
        // 构造一个job
        JobKey jobKey = JobKey.jobKey(sysJob.getJobId().toString(), sysJob.getJobGroup());
        String status ="";
        TriggerKey triggerKey = TriggerKey.triggerKey(sysJob.getJobId().toString(), sysJob.getJobGroup());
        Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);
        switch (triggerState) {
            case NORMAL:
                status="正常";
                break;
            case PAUSED:
                status="暂停";
                break;
            case COMPLETE:
                status="完成";
                break;
            case ERROR:
                status="错误";
                break;
            case BLOCKED:
                status="阻塞";
                break;
            default:
                status="不存在该任务";
                break;
        }
        return status;
    }
 
    private static void getMisfirePolicy(SysJob sysJob, CronScheduleBuilder cronScheduleBuilder) {
        String s= sysJob.getMisfirePolicy();
        if(s.equals(JobEnum.MISFIRE_DEFAULT.getCode())){
        }else if(s.equals(JobEnum.MISFIRE_IGNORE.getCode())){
            cronScheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires();
        } else if(s.equals(JobEnum.MISFIRE_FIRE_AND_PROCEED.getCode())){
            cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed();
        } else if(s.equals(JobEnum.MISFIRE_DO_NOTHING.getCode())){
            cronScheduleBuilder.withMisfireHandlingInstructionDoNothing();
        }else{
            throw new RuntimeException("The task misfire policy '" + sysJob.getMisfirePolicy() + "' cannot be used in cron schedule tasks");
        }
    }
 
    public static void invokeMethod(Object bean, String methodName) throws Exception {
        Method method = bean.getClass().getMethod(methodName);
        method.invoke(bean);
    }
    public static void runJob(String invokeTarget){
        String[] parts = invokeTarget.split("\\.");
        String beanName = parts[0];
        String methodName = parts[1];
        Object bean = SpringContextHolder.getBean(beanName);
        try {
            QuartzUtil.invokeMethod(bean, methodName);
        } catch (Exception e) {
            throw new RuntimeException("Error running job", e);
        }
    }



}
